home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / frntsdk1.cpt / Frontier SDK 1.0 ƒ / Applet Toolkit / scrollbar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-03  |  14.3 KB  |  745 lines

  1.  
  2. /*⌐ Copyright 1988-1991 UserLand Software, Inc.  All Rights Reserved.*/
  3.  
  4.  
  5. #include "appletinternal.h"
  6. #include "ops.h"
  7. #include "quickdraw.h"
  8. #include "appletmain.h"
  9. #include "scrollbar.h"
  10.  
  11.  
  12.  
  13. #define idvertbar 256
  14. #define idhorizbar 257
  15.  
  16.  
  17. static boolean scrollbarpushclip (hdlscrollbar hscrollbar) {
  18.     
  19.     /*
  20.     11/19/90 DW: patch things up for the table displayer, and perhaps others in
  21.     the future.  if the scrollbar is of trivial height, we disable the drawing
  22.     that's about to happen.  we were getting one-pixel high scrollbars being
  23.     drawn.
  24.     */
  25.     
  26.     Rect r = (**hscrollbar).contrlRect;
  27.     
  28.     if ((r.bottom - r.top) == 1)
  29.         r.bottom = r.top;
  30.         
  31.     return (pushclip (r));
  32.     } /*scrollbarpushclip*/
  33.     
  34.     
  35. void validscrollbar (hdlscrollbar hscrollbar) {
  36.  
  37.     register hdlscrollbar h = hscrollbar;
  38.     
  39.     if (h != nil) 
  40.         validrect ((**h).contrlRect);
  41.     } /*validscrollbar*/
  42.     
  43.     
  44. static invalscrollbar (hdlscrollbar hscrollbar) {
  45.  
  46.     register hdlscrollbar h = hscrollbar;
  47.     
  48.     if (h != nil) 
  49.         invalrect ((**h).contrlRect);
  50.     } /*invalscrollbar*/
  51.     
  52.     
  53. boolean pointinscrollbar (Point pt, hdlscrollbar hscrollbar) {
  54.  
  55.     register hdlscrollbar h = hscrollbar;
  56.     
  57.     if (h == nil) /*defensive driving*/
  58.         return (false);
  59.         
  60.     return (pointinrect (pt, (**h).contrlRect));
  61.     } /*pointinscrollbar*/
  62.     
  63.     
  64. void enablescrollbar (hdlscrollbar hscrollbar) {
  65.     
  66.     register hdlscrollbar h = hscrollbar;
  67.     
  68.     if (h == nil) /*defensive driving*/
  69.         return;
  70.         
  71.     scrollbarpushclip (h);
  72.         
  73.     HiliteControl (h, 0);
  74.     
  75.     /*validscrollbar (h);*/
  76.     
  77.     popclip ();
  78.     } /*enablescrollbar*/
  79.     
  80.     
  81. void disablescrollbar (hdlscrollbar hscrollbar) {
  82.     
  83.     register hdlscrollbar h = hscrollbar;
  84.     
  85.     if (h == nil) /*defensive driving*/
  86.         return;
  87.         
  88.     scrollbarpushclip (h);
  89.         
  90.     HiliteControl (h, -1);
  91.     
  92.     /*validscrollbar (h);*/
  93.     
  94.     popclip ();
  95.     } /*disablescrollbar*/
  96.     
  97.     
  98. void activatescrollbar (hdlscrollbar hscrollbar, boolean flactivate) {
  99.     
  100.     if (flactivate)
  101.         enablescrollbar (hscrollbar);
  102.     else
  103.         disablescrollbar (hscrollbar);
  104.     } /*activatescrollbar*/
  105.     
  106.     
  107. void getscrollbarinfo (hscrollbar, minscroll, maxscroll, current) hdlscrollbar hscrollbar; short *minscroll, *maxscroll, *current; {
  108.     
  109.     register hdlscrollbar h = hscrollbar;
  110.     
  111.     if (h == nil) { /*defensive driving*/
  112.     
  113.         *minscroll = *maxscroll = *current = 0;
  114.         
  115.         return;
  116.         }
  117.     
  118.     *minscroll = GetCtlMin (h);
  119.         
  120.     *maxscroll = GetCtlMax (h);
  121.         
  122.     *current = GetCtlValue (h);
  123.     } /*getscrollbarinfo*/
  124.     
  125.     
  126. short getscrollbarcurrent (hdlscrollbar hscrollbar) {
  127.     
  128.     short minscroll, maxscroll, current;
  129.     
  130.     getscrollbarinfo (hscrollbar, &minscroll, &maxscroll, ¤t);
  131.     
  132.     return (current);
  133.     } /*getscrollbarcurrent*/
  134.     
  135.     
  136. void showscrollbar (hdlscrollbar hscrollbar) {
  137.     
  138.     register hdlscrollbar h = hscrollbar;
  139.     
  140.     if (h == nil) /*defensive driving*/
  141.         return;
  142.         
  143.     scrollbarpushclip (h);
  144.         
  145.     ShowControl (h); /*no effect if scrollbar is already visible, according to IM-1*/
  146.     
  147.     popclip ();
  148.     
  149.     /*don't validate the scrollbar rect, ShowControl might not draw it...*/
  150.     } /*showscrollbar*/
  151.     
  152.     
  153. void hidescrollbar (hdlscrollbar hscrollbar) {
  154.     
  155.     register hdlscrollbar h = hscrollbar;
  156.     
  157.     if (h == nil) /*defensive driving*/
  158.         return;
  159.         
  160.     scrollbarpushclip (h);
  161.         
  162.     HideControl (h);
  163.     
  164.     popclip ();
  165.     
  166.     invalrect ((**h).contrlRect);
  167.     } /*hidescrollbar*/
  168.     
  169.  
  170. void drawscrollbar (hdlscrollbar hscrollbar) {
  171.     
  172.     register hdlscrollbar h = hscrollbar;
  173.     
  174.     if (h == nil) /*defensive driving*/
  175.         return;
  176.         
  177.     scrollbarpushclip (h);
  178.     
  179.     Draw1Control (h);
  180.     
  181.     popclip ();
  182.     
  183.     validscrollbar (h);
  184.     } /*drawscrollbar*/
  185.     
  186.     
  187. void displayscrollbar (hdlscrollbar hscrollbar) {
  188.     
  189.     /*
  190.     the caller is saying that we should enable it if there is enough 
  191.     material to enable scrolling.
  192.     */
  193.     
  194.     register hdlscrollbar h = hscrollbar;
  195.     short minscroll, maxscroll, current;
  196.     
  197.     if (h == nil) /*defensive driving*/
  198.         return;
  199.         
  200.     getscrollbarinfo (h, &minscroll, &maxscroll, ¤t);
  201.     
  202.     if (minscroll <= maxscroll) /*there's something to scroll to*/
  203.         enablescrollbar (h);
  204.     else
  205.         disablescrollbar (h);
  206.         
  207.     drawscrollbar (h);
  208.     } /*displayscrollbar*/
  209.     
  210.     
  211. void setscrollbarinfo (hdlscrollbar hscrollbar, short minscroll, short maxscroll, short current) {
  212.     
  213.     /*
  214.     set the bounds of the scrollbar, and its current value.
  215.     
  216.     if the current info agrees with the parameters we do nothing, 
  217.     avoiding unpleasant flicker.
  218.     
  219.     disables drawing while setting the values, and draws it when 
  220.     all three values have been set.  avoids inconsistent displays.
  221.     */
  222.     
  223.     register hdlscrollbar h = hscrollbar;
  224.     short curmin, curmax, curval;
  225.     
  226.     if (h == nil) /*defensive driving*/
  227.         return;
  228.     
  229.     getscrollbarinfo (h, &curmin, &curmax, &curval);
  230.     
  231.     if ((minscroll == curmin) && (maxscroll == curmax) && (current == curval))
  232.         return; /*nothing to do*/
  233.     
  234.     pushemptyclip (); /*disable drawing*/
  235.     
  236.     SetCtlMax (h, maxscroll);
  237.     
  238.     SetCtlMin (h, minscroll);
  239.     
  240.     SetCtlValue (h, current);
  241.     
  242.     popclip ();
  243.     
  244.     displayscrollbar (h);
  245.     } /*setscrollbarinfo*/
  246.     
  247.     
  248. void setscrollbarminmax (hdlscrollbar hscrollbar, short minscroll, short maxscroll) {
  249.     
  250.     register hdlscrollbar h = hscrollbar;
  251.     short curmin, curmax, curval;
  252.     
  253.     if (h == nil) /*defensive driving*/
  254.         return;
  255.     
  256.     getscrollbarinfo (h, &curmin, &curmax, &curval);
  257.     
  258.     if ((minscroll != curmin) || (maxscroll != curmax)) {
  259.     
  260.         setscrollbarinfo (h, minscroll, maxscroll, curval);
  261.         }
  262.     } /*setscrollbarminmax*/
  263.     
  264.     
  265. void setscrollbarcurrent (hdlscrollbar hscrollbar, short current) {
  266.  
  267.     register hdlscrollbar h = hscrollbar;
  268.     
  269.     if (h == nil) /*defensive driving*/
  270.         return;
  271.     
  272.     scrollbarpushclip (h);
  273.     
  274.     SetCtlValue (h, current);
  275.     
  276.     popclip ();
  277.     } /*setscrollbarcurrent*/
  278.  
  279.  
  280. short getscrollbarwidth (void) {
  281.     
  282.     return (16); /*standard Macintosh scrollbars*/
  283.     } /*getscrollbarwidth*/
  284.  
  285.  
  286. boolean newscrollbar (WindowPtr w, boolean flvert, hdlscrollbar *hscrollbar) {
  287.     
  288.     /*
  289.     create a new scroll bar linked into the control list of the indicated
  290.     window.  
  291.     
  292.     we need to know if it is a vertical or horizontal scrollbar so we can
  293.     choose the proper resource template.  we use a CDEF that has different
  294.     specs for horiz and vertical scrollbars.
  295.     */
  296.     
  297.     register hdlscrollbar h;
  298.     register short resnum;
  299.     
  300.     if (flvert)
  301.         resnum = idvertbar;
  302.     else
  303.         resnum = idhorizbar;
  304.     
  305.     *hscrollbar = h = GetNewControl (resnum, w);
  306.     
  307.     return (h != nil);
  308.     } /*newscrollbar*/
  309.     
  310.     
  311. void disposescrollbar (hdlscrollbar hscrollbar) {
  312.     
  313.     register hdlscrollbar h = hscrollbar;
  314.     
  315.     if (h != nil)
  316.         DisposeControl (h);
  317.     } /*disposescrollbar*/
  318.     
  319.     
  320. void getscrollbarrect (hdlscrollbar hscrollbar, Rect *r) {
  321.  
  322.     register hdlscrollbar h = hscrollbar;
  323.     
  324.     if (h != nil) 
  325.         *r = (**h).contrlRect;
  326.     else
  327.         zerorect (r);
  328.     } /*getscrollbarrect*/
  329.     
  330.     
  331. void setscrollbarrect (hdlscrollbar hscrollbar, Rect r) {
  332.  
  333.     register hdlscrollbar h = hscrollbar;
  334.     
  335.     if (h != nil) {
  336.         
  337.         HideControl (h);
  338.         
  339.         SizeControl (h, r.right - r.left, r.bottom - r.top);
  340.         
  341.         MoveControl (h, r.left, r.top);
  342.         }
  343.     } /*setscrollbarrect*/
  344.     
  345.     
  346. void scrollbarflushright (Rect r, hdlscrollbar hscrollbar) {
  347.     
  348.     register hdlscrollbar h = hscrollbar;
  349.     register short width;
  350.     
  351.     if (h == nil) /*defensive driving*/
  352.         return;
  353.         
  354.     width = getscrollbarwidth ();
  355.     
  356.     HideControl (h);
  357.     
  358.     SizeControl (h, width, r.bottom - r.top + 2);
  359.     
  360.     MoveControl (h, r.right - width + 1, r.top - 1);
  361.     } /*scrollbarflushright*/
  362.     
  363.     
  364. void scrollbarflushbottom (Rect r, hdlscrollbar hscrollbar) {
  365.     
  366.     register hdlscrollbar h = hscrollbar;
  367.     register short width;
  368.     
  369.     if (h == nil) /*defensive driving*/
  370.         return;
  371.         
  372.     width = getscrollbarwidth ();
  373.         
  374.     HideControl (h);
  375.     
  376.     SizeControl (hscrollbar, r.right - r.left, width);
  377.         
  378.     MoveControl (hscrollbar, r.left, r.bottom - width + 1);
  379.     } /*scrollbarflushbottom*/
  380.     
  381.     
  382. boolean findscrollbar (Point pt, WindowPtr w, hdlscrollbar *hscrollbar, short *scrollbarpart) {
  383.     
  384.     *scrollbarpart = FindControl (pt, w, hscrollbar);
  385.     
  386.     return (*hscrollbar != nil);
  387.     } /*findscrollbar*/
  388.     
  389.     
  390. boolean scrollbarhit (hdlscrollbar hscrollbar, short part, boolean *flup, boolean *flpage) {
  391.     
  392.     /*
  393.     can be called by a routine that tracks a mouse hit in a scroll bar.
  394.     
  395.     return true if it represents a valid scroll action, according to the info
  396.     stored in the scrollbar handle.
  397.     
  398.     return false if the indicated action would move beyond the min or max for
  399.     the scrollbar.
  400.     
  401.     set flup and flpage according to the indicated scrollbar part.
  402.     */
  403.     
  404.     register hdlscrollbar h = hscrollbar;
  405.     short minscroll, maxscroll, current;
  406.     
  407.     if (h == nil) /*defensive driving*/
  408.         return;
  409.         
  410.     getscrollbarinfo (h, &minscroll, &maxscroll, ¤t);
  411.     
  412.     switch (part) {
  413.     
  414.         case inUpButton:
  415.             *flup = false; /*scroll text down*/
  416.             
  417.             *flpage = false;
  418.             
  419.             return (current > minscroll);
  420.             
  421.         case inDownButton:
  422.             *flup = true; /*scroll text up*/
  423.             
  424.             *flpage = false;
  425.             
  426.             return (current < maxscroll);
  427.             
  428.         case inPageUp:
  429.             *flup = false; /*scroll text down*/
  430.             
  431.             *flpage = true; 
  432.             
  433.             return (current > minscroll);
  434.             
  435.         case inPageDown:
  436.             *flup = true; /*scroll text up*/
  437.             
  438.             *flpage = true;
  439.             
  440.             return (current < maxscroll);
  441.         } /*switch*/
  442.         
  443.     return (false); /*fell through the switch statement*/
  444.     } /*scrollbarhit*/
  445.     
  446.  
  447. void resetappscrollbars (appwindow) hdlappwindow appwindow; {
  448.     
  449.     setappwindow (appwindow);
  450.     
  451.     (*app.resetscrollbarscallback) ();
  452.     } /*resetappscrollbars*/
  453.     
  454.  
  455. void resizeappscrollbars (appwindow) hdlappwindow appwindow; {
  456.     
  457.     if (app.horizscroll || app.vertscroll) {
  458.         
  459.         register hdlappwindow ha = appwindow;
  460.         register short scrollbarwidth;
  461.         Rect rwholewindow = (**ha).windowrect;
  462.         Rect r;
  463.         
  464.         scrollbarwidth = getscrollbarwidth ();
  465.     
  466.         if (app.vertscroll) {
  467.     
  468.             r = rwholewindow; 
  469.         
  470.             r.bottom -= scrollbarwidth - 1;
  471.             
  472.             r.top += app.statuspixels; /*leave room for status bar at top of window*/
  473.             
  474.             r.top = (**ha).contentrect.top;
  475.         
  476.             scrollbarflushright (r, (**ha).vertbar);
  477.             }
  478.         
  479.         if (app.horizscroll) {
  480.         
  481.             r = rwholewindow; 
  482.         
  483.             r.right -= scrollbarwidth - 2;
  484.         
  485.             r.left -= 1; 
  486.             
  487.             scrollbarflushbottom (r, (**ha).horizbar);
  488.             }
  489.         }
  490.     } /*resizeappscrollbars*/
  491.     
  492.     
  493. void showappscrollbars (appwindow) hdlappwindow appwindow; {
  494.     
  495.     register hdlappwindow ha = appwindow;
  496.     
  497.     if (app.vertscroll)
  498.         showscrollbar ((**ha).vertbar);
  499.     
  500.     if (app.horizscroll)
  501.         showscrollbar ((**ha).horizbar);
  502.     } /*showappscrollbars*/
  503.     
  504.     
  505. void updateappscrollbars (appwindow) hdlappwindow appwindow; {
  506.     
  507.     register hdlappwindow ha = appwindow;
  508.         
  509.     if (app.vertscroll) {
  510.         
  511.         showscrollbar ((**ha).vertbar);
  512.         
  513.         drawscrollbar ((**ha).vertbar);
  514.         }
  515.         
  516.     if (app.horizscroll) {
  517.         
  518.         showscrollbar ((**ha).horizbar);
  519.         
  520.         drawscrollbar ((**ha).horizbar);
  521.         }
  522.     } /*updateappscrollbars*/
  523.     
  524.     
  525. void activateappscrollbars (appwindow, flactivate) hdlappwindow appwindow; boolean flactivate; {
  526.     
  527.     register hdlappwindow ha = appwindow;
  528.     
  529.     if (app.vertscroll)     
  530.         activatescrollbar ((**ha).vertbar, flactivate);
  531.         
  532.     if (app.horizscroll)     
  533.         activatescrollbar ((**ha).horizbar, flactivate);
  534.     } /*activateappscrollbars*/
  535.     
  536.     
  537. tydirection scrolldirection (boolean flvert, boolean flup) {
  538.  
  539.     register tydirection dir;
  540.     
  541.     if (flvert)
  542.         if (flup)
  543.             dir = up;
  544.         else
  545.             dir = down;
  546.     else
  547.         if (flup)
  548.             dir = left;
  549.         else
  550.             dir = right; 
  551.     
  552.     return (dir);
  553.     } /*scrolldirection*/ 
  554.  
  555.  
  556. static pascal void apphorizscroll (hdlscrollbar ctrl, short part) {
  557.     
  558.     register tydirection dir;
  559.     boolean flleft, flpage;
  560.     
  561.     if (!scrollbarhit (ctrl, part, &flleft, &flpage))
  562.         return;
  563.         
  564.     dir = scrolldirection (false, flleft);
  565.         
  566.     (*app.scrollcallback) (dir, flpage, 1);
  567.     } /*apphorizscroll*/
  568.  
  569.  
  570. static pascal void appvertscroll (hdlscrollbar sb, short part) {
  571.     
  572.     register tydirection dir;
  573.     boolean flup, flpage;
  574.     
  575.     if (!scrollbarhit (sb, part, &flup, &flpage))
  576.         return;
  577.     
  578.     dir = scrolldirection (true, flup);
  579.         
  580.     (*app.scrollcallback) (dir, flpage, 1);
  581.     } /*appvertscroll*/
  582.  
  583.  
  584. void scrollappwindow (boolean flvert, hdlscrollbar sb, short part, Point pt) {
  585.     
  586.     register short oldscrollbarcurrent;
  587.     register short ctscroll;
  588.     tydirection dir;
  589.     
  590.     if (part == inThumb) {
  591.         
  592.         oldscrollbarcurrent = getscrollbarcurrent (sb);
  593.         
  594.         TrackControl (sb, pt, nil);
  595.         
  596.         ctscroll = getscrollbarcurrent (sb) - oldscrollbarcurrent;
  597.         
  598.         dir = scrolldirection (flvert, ctscroll > 0);
  599.         
  600.         (*app.scrollcallback) (dir, false, abs (ctscroll));
  601.         }
  602.     else {
  603.         if (flvert)
  604.             TrackControl (sb, pt, &appvertscroll);
  605.         else
  606.             TrackControl (sb, pt, &apphorizscroll);
  607.         }
  608.     } /*scrollappwindow*/
  609.     
  610.  
  611. static boolean defaultscroll (tydirection dir, boolean flpage, short ctscroll) {
  612.     
  613.     /*
  614.     if the applet didn't define a scrolling routine, this routine will
  615.     be called to do the scrolling. it implements a very bare-bones way
  616.     of scrolling, that often is just what you want...
  617.     */
  618.     
  619.     register hdlappwindow ha = app.appwindow;
  620.     register short ct = ctscroll;
  621.     register short dh = 0, dv = 0;
  622.     Rect r;
  623.     
  624.     if ((ct == 1) && (!flpage)) { /*it's heuristic time!*/
  625.         
  626.         if (!optionkeydown ()) {
  627.             
  628.             ct = getfontheight (); /*scroll by this (reasonable) amount*/
  629.             
  630.             /*user holds down the option key to get a 2-pixel scroll*/
  631.             }
  632.         }
  633.     
  634.     if (ct % 2) /*it's an odd number*/
  635.         ct++;
  636.     
  637.     r = (**ha).contentrect;
  638.     
  639.     switch (dir) {
  640.         
  641.         case down:
  642.             if (flpage)
  643.                 dv = -(r.bottom - r.top);
  644.             else
  645.                 dv = -ct;
  646.             
  647.             break;
  648.             
  649.         case up:
  650.             if (flpage)
  651.                 dv = r.bottom - r.top;
  652.             else
  653.                 dv = ct;
  654.             
  655.             break;
  656.         
  657.         case right:
  658.             if (flpage)
  659.                 dh = -(r.right - r.left);
  660.             else
  661.                 dh = -ct;
  662.                 
  663.             break;
  664.             
  665.         case left:
  666.             if (flpage)
  667.                 dh = r.right - r.left;
  668.             else
  669.                 dh = ct;
  670.                 
  671.             break;
  672.             
  673.         default:
  674.             return (false);
  675.         } /*switch*/
  676.     
  677.     if (dv != 0) {
  678.         
  679.         register short x;
  680.         short vertmin, vertmax, vertcurrent;
  681.         
  682.         getscrollbarinfo ((**ha).vertbar, &vertmin, &vertmax, &vertcurrent);
  683.         
  684.         vertcurrent = (**ha).scrollorigin.v; /*the scrollbar lies, fix it*/
  685.         
  686.         x = vertcurrent + dv;
  687.     
  688.         x = max (x, vertmin);
  689.     
  690.         x = min (x, vertmax);
  691.         
  692.         dv = vertcurrent - x;
  693.         
  694.         vertcurrent = x;
  695.         
  696.         setscrollbarinfo ((**ha).vertbar, vertmin, vertmax, vertcurrent);
  697.         
  698.         (**ha).scrollorigin.v = x;
  699.         }
  700.     
  701.     if (dh != 0) {
  702.         
  703.         register short x;
  704.         short horizmin, horizmax, horizcurrent;
  705.         
  706.         getscrollbarinfo ((**ha).horizbar, &horizmin, &horizmax, &horizcurrent);
  707.         
  708.         horizcurrent = (**ha).scrollorigin.h; /*the scrollbar lies, fix it*/
  709.         
  710.         x = horizcurrent + dh;
  711.     
  712.         x = max (x, horizmin);
  713.     
  714.         x = min (x, horizmax);
  715.         
  716.         dh = horizcurrent - x;
  717.         
  718.         horizcurrent = x;
  719.         
  720.         setscrollbarinfo ((**ha).horizbar, horizmin, horizmax, horizcurrent);
  721.         
  722.         (**ha).scrollorigin.h = x;
  723.         }
  724.     
  725.     if ((dh != 0) || (dv != 0)) {
  726.     
  727.         scrollrect (r, dh, dv);
  728.     
  729.         updateappwindow (ha);
  730.         }
  731.         
  732.     return (true);
  733.     } /*defaultscroll*/
  734.     
  735.     
  736. void installscroll (void) {
  737.     
  738.     if ((app.scrollcallback == nil) && ((app.horizscroll) || (app.vertscroll)))
  739.         app.scrollcallback = &defaultscroll;
  740.     } /*installscroll*/
  741.     
  742.     
  743.  
  744.  
  745.